import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

class _BothDirectionTest extends StatefulWidget {
  @override
  _BothDirectionTestState createState() => _BothDirectionTestState();
}

class _BothDirectionTestState extends State<_BothDirectionTest> {
  double _top = 40.0;
  double _left = 0.0;

  double _left2 = 0.0;
  double _left3 = 0.0;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned(
          top: 10,
          child: Text(
              "1. 单种手势冲突，水平和垂直移动 onHorizontalDragUpdate & onVerticalDragUpdate。哪边的分量更大，哪边胜出"),
        ),
        Positioned(
          top: _top,
          left: _left,
          child: GestureDetector(
            child: CircleAvatar(child: Text("A")),
            //垂直方向拖动事件
            onVerticalDragUpdate: (DragUpdateDetails details) {
              setState(() {
                _top += details.delta.dy;
              });
            },
            onHorizontalDragUpdate: (DragUpdateDetails details) {
              setState(() {
                _left += details.delta.dx;
              });
            },
          ),
        ),
        Positioned(
          top: 100,
          child: Text("2. 多种手势冲突，onTapUp & onHorizontalDragEnd, 后者胜出"),
        ),
        Positioned(
          left: _left2,
          top: 120,
          child: GestureDetector(
            child: CircleAvatar(child: Text("B")), //要拖动和点击的widget
            onHorizontalDragUpdate: (DragUpdateDetails details) {
              setState(() {
                _left2 += details.delta.dx;
              });
            },
            onHorizontalDragEnd: (details) {
              print("onHorizontalDragEnd");
            },
            onTapDown: (details) {
              print("down");
            },
            onTapUp: (details) {
              print("up");
            },
          ),
        ),
        Positioned(
          top: 180,
          child: Text(
              "3. 比如在轮播中：手指按下时，轮播暂停，抬起时恢复轮播，但是呢，onHorizontalDragEnd也需要，那就必须得解决手势冲突了: 改一个为Listener"),
        ),
        Positioned(
          left: _left3,
          top: 210,
          child: Listener(
            onPointerDown: (details) {
              print("down");
            },
            onPointerUp: (details) {
              //会触发
              print("up");
            },
            child: GestureDetector(
              child: CircleAvatar(child: Text("C")), //要拖动和点击的widget
              onHorizontalDragUpdate: (DragUpdateDetails details) {
                setState(() {
                  _left3 += details.delta.dx;
                });
              },
              onHorizontalDragEnd: (details) {
                print("onHorizontalDragEnd");
              },
            ),
          ),
        ),
      ],
    );
  }
}

class Demo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text("1. 父组件和子组件会进行手势竞争判断，子组件胜出"),
        GestureDetector(
          //GestureDetector2
          onTapUp: (x) => print("2"), // 监听父组件 tapUp 手势
          child: Container(
            width: 200,
            height: 200,
            color: Colors.red,
            alignment: Alignment.center,
            child: GestureDetector(
              //GestureDetector1
              onTapUp: (x) => print("1"), // 监听子组件 tapUp 手势
              child: Container(
                width: 50,
                height: 50,
                color: Colors.grey,
                child: Text("子组件"),
              ),
            ),
          ),
        ),
        SizedBox(height: 10),
        Text("2. 为什么拖动手势不能放在这儿呢？难道是因为从原点开始算距离吗？"),
        // _BothDirectionTest(),
        SizedBox(height: 30),
        Text("3. 手势冲突"),
        Text("原因：手势级别的，GestureDetector, 发生冲突后只会有一个竞争出来，不清楚为什么要这么设计"),
        Text("解决办法："),
        Text("1. 不要嵌套使用GestureDetector, 换一个成Listener就好了"),
        Text("2. 通过自定义 Recognizer, 和listener一样，只用替换一个就好"),
        customGestureDetector(
          onTapUp: (x) => print("2"), // 监听父组件 tapUp 手势
          child: Container(
            width: 200,
            height: 200,
            color: Colors.red,
            alignment: Alignment.center,
            child: GestureDetector(
              onTapUp: (x) => print("1"), // 监听子组件 tapUp 手势
              child: Container(
                width: 50,
                height: 50,
                color: Colors.grey,
                child: Text("子组件"),
              ),
            ),
          ),
        ),
      ],
    );
  }
}

class CustomTapGestureRecognizer extends TapGestureRecognizer {
  @override
  void rejectGesture(int pointer) {
    //不，我不要失败，我要成功
    //super.rejectGesture(pointer);
    //宣布成功
    super.acceptGesture(pointer);
  }
}

//创建一个新的GestureDetector，用我们自定义的 CustomTapGestureRecognizer 替换默认的
RawGestureDetector customGestureDetector({
  GestureTapCallback? onTap,
  GestureTapDownCallback? onTapDown,
  GestureTapUpCallback? onTapUp,
  Widget? child,
}) {
  return RawGestureDetector(
    gestures: {
      CustomTapGestureRecognizer:
          GestureRecognizerFactoryWithHandlers<CustomTapGestureRecognizer>(
        () => CustomTapGestureRecognizer(),
        (detector) {
          // detector.onTap = onTap;
          // detector.onTapDown = onTapDown;
          // detector.onTapUp = onTapUp;

          detector
            ..onTap = onTap
            ..onTapDown = onTapDown
            ..onTapUp = onTapUp;
          // ..onTapCancel = onTapDown;
        },
      )
    },
    child: child,
  );
}

void main(List<String> args) {
  runApp(MaterialApp(
    home: Scaffold(
      body: Demo(),
      // body: _BothDirectionTest(),
    ),
  ));
}
